package com.google.code.swingonfire.component.calendar;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.Calendar;

public class DefaultJCalendarBackgroundRenderer implements JCalendarBackgroundRenderer
{

    private final Color backgroundColor = Color.WHITE;

    private final Color horizontalHeaderLineColor = new Color(0xb3b3b3);
    private final float horizontalHeaderLineThickness = 1.5f;

    private final Color verticalHeaderLineColor = new Color(0xb3b3b3);
    private final float verticalHeaderLineThickness = 1.5f;

    private final Color horizontalLineColor = new Color(0xe8e8e8);
    private final float horizontalLineThickness = 1.0f;

    private final Color verticalLineColor = new Color(0xe8e8e8);
    private final float verticalLineThickness = 1.0f;

    /**
     * {@inheritDoc}
     */
    @Override
    public void drawMonthTableBackground(JCalendarModel model, int month, int year, Graphics2D g, int width,
        int height, int[] rows, int[] columns, boolean weekOfYearVisible)
    {
        prepare(g);

        clear((Graphics2D) g.create(), width, height);
        drawMonthTableBackground(model, month, year, (Graphics2D) g.create(), rows, columns, weekOfYearVisible);
        drawMonthTableLines((Graphics2D) g.create(), rows, columns, weekOfYearVisible);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void drawYearTableBackground(JCalendarModel model, int year, Graphics2D g, int width, int height,
        int[] rows, int[] columns)
    {
        prepare(g);

        clear((Graphics2D) g.create(), width, height);
        drawYearTableBackground(model, year, (Graphics2D) g.create(), rows, columns);
        drawYearTableLines((Graphics2D) g.create(), rows, columns);
    }

    protected void clear(Graphics2D g, int width, int height)
    {
        if (backgroundColor == null)
        {
            g.setComposite(AlphaComposite.Clear);
        }
        else
        {
            g.setColor(backgroundColor);
        }

        g.fillRect(0, 0, width, height);
    }

    protected void drawMonthTableBackground(JCalendarModel model, int month, int year, Graphics2D g, int[] rows,
        int[] columns, boolean weekOfYearVisible)
    {
        for (int x = ((weekOfYearVisible) ? 1 : 0); x < (columns.length - 1); x += 1)
        {
            Color background =
                model
                    .getDayOfWeekBackground(((((model.getFirstDayOfWeek() - 1) + x) - ((weekOfYearVisible) ? 1 : 0)) % 7) + 1);

            if (background != null)
            {
                g.setColor(background);
                g.fillRect(columns[x], rows[0], columns[x + 1] - columns[x], rows[1] - rows[0]);
            }
        }

        Calendar current = JMonthTableModel.getFirstDayOfCalendar(model, month, year);

        for (int y = 1; y < 7; y += 1)
        {
            if (weekOfYearVisible)
            {
                Color background = model.getWeekOfYearBackground(current);

                if (background != null)
                {
                    g.setColor(background);
                    g.fillRect(columns[0], rows[y], columns[1] - columns[0], rows[y + 1] - rows[y]);
                }
            }

            for (int x = ((weekOfYearVisible) ? 1 : 0); x < (columns.length - 1); x += 1)
            {
                Color background = model.getDayBackground(current, month == current.get(Calendar.MONTH));

                if (background != null)
                {
                    g.setColor(background);
                    g.fillRect(columns[x], rows[y], columns[x + 1] - columns[x], rows[y + 1] - rows[y]);
                }

                current.add(Calendar.DAY_OF_YEAR, 1);
            }
        }
    }

    protected void drawMonthTableLines(Graphics2D g, int[] rows, int[] columns, boolean weekOfYearVisible)
    {
        if ((verticalLineColor != null) && (verticalLineThickness > 0))
        {
            g.setColor(verticalLineColor);
            g.setStroke(new BasicStroke(verticalLineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

            for (int i = ((weekOfYearVisible) ? 2 : 1); i < (columns.length - 1); i += 1)
            {
                g.drawLine(columns[i], rows[0], columns[i], rows[7]);
            }
        }

        if ((horizontalLineColor != null) && (horizontalLineThickness > 0))
        {
            g.setColor(horizontalLineColor);
            g.setStroke(new BasicStroke(horizontalLineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

            for (int i = 2; i < 7; i += 1)
            {
                g.drawLine(columns[0], rows[i], columns[columns.length - 1], rows[i]);
            }
        }

        if (weekOfYearVisible)
        {
            if ((verticalHeaderLineColor != null) && (verticalHeaderLineThickness > 0))
            {
                g.setColor(verticalHeaderLineColor);
                g.setStroke(new BasicStroke(verticalHeaderLineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

                g.drawLine(columns[1], rows[0], columns[1], rows[7]);
            }
            else if ((verticalLineColor != null) && (verticalLineThickness > 0))
            {
                g.setColor(verticalLineColor);
                g.setStroke(new BasicStroke(verticalLineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

                g.drawLine(columns[1], rows[0], columns[1], rows[7]);
            }
        }

        if ((horizontalHeaderLineColor != null) && (horizontalHeaderLineThickness > 0))
        {
            g.setColor(horizontalHeaderLineColor);
            g.setStroke(new BasicStroke(horizontalHeaderLineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

            g.drawLine(columns[0], rows[1], columns[columns.length - 1], rows[1]);
        }
        else if ((horizontalLineColor != null) && (horizontalLineThickness > 0))
        {
            g.setColor(horizontalLineColor);
            g.setStroke(new BasicStroke(horizontalLineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

            g.drawLine(columns[0], rows[1], columns[columns.length - 1], rows[1]);
        }

    }

    protected void drawYearTableBackground(JCalendarModel model, int year, Graphics2D g, int[] rows, int[] columns)
    {
        // TODO Auto-generated method stub

    }

    protected void drawYearTableLines(Graphics2D g, int[] rows, int[] columns)
    {
        if ((verticalLineColor != null) && (verticalLineThickness > 0))
        {
            g.setColor(verticalLineColor);
            g.setStroke(new BasicStroke(verticalLineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

            for (int i = 1; i < (columns.length - 1); i += 1)
            {
                g.drawLine(columns[i], rows[0], columns[i], rows[rows.length - 1]);
            }
        }

        if ((horizontalLineColor != null) && (horizontalLineThickness > 0))
        {
            g.setColor(horizontalLineColor);
            g.setStroke(new BasicStroke(horizontalLineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

            for (int i = 1; i < (rows.length - 1); i += 1)
            {
                g.drawLine(columns[0], rows[i], columns[columns.length - 1], rows[i]);
            }
        }
    }

    private void prepare(Graphics2D g)
    {
        g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
        g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    }

}
